using System;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
using Oracle.ManagedDataAccess.Client;
using OracleInternal.Common;

namespace Oracle.ManagedDataAccess.Types
{
	[Serializable]
	[XmlSchemaProvider("GetXsdType")]
	public struct OracleBinary : IComparable, INullable, IXmlSerializable
	{
		internal byte[] m_value;

		private bool m_bNotNull;

		public static readonly OracleBinary Null;

		public bool IsNull => !m_bNotNull;

		public int Length
		{
			get
			{
				if (m_bNotNull)
				{
					return m_value.Length;
				}
				throw new OracleNullValueException();
			}
		}

		public byte this[int index]
		{
			get
			{
				if (m_bNotNull)
				{
					return m_value[index];
				}
				throw new OracleNullValueException();
			}
		}

		public byte[] Value
		{
			get
			{
				if (m_bNotNull)
				{
					byte[] array = new byte[m_value.Length];
					m_value.CopyTo(array, 0);
					return array;
				}
				throw new OracleNullValueException();
			}
		}

		public OracleBinary(byte[] data)
		{
			if (ProviderConfig.m_bTraceLevelPublic)
			{
				Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Entry, OracleTraceClassName.OracleBinary, OracleTraceFuncName.ctor);
			}
			if (data != null)
			{
				m_bNotNull = true;
				m_value = new byte[data.Length];
				data.CopyTo(m_value, 0);
			}
			else
			{
				m_bNotNull = false;
				m_value = null;
			}
			if (ProviderConfig.m_bTraceLevelPublic)
			{
				Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Exit, OracleTraceClassName.OracleBinary, OracleTraceFuncName.ctor);
			}
		}

		internal OracleBinary(byte[] data, bool bCopy)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, OracleTraceTag.Entry, OracleTraceClassName.OracleBinary, OracleTraceFuncName.ctor);
			}
			if (data != null)
			{
				m_bNotNull = true;
				if (bCopy)
				{
					m_value = new byte[data.Length];
					data.CopyTo(m_value, 0);
				}
				else
				{
					m_value = data;
				}
			}
			else
			{
				m_bNotNull = false;
				m_value = null;
			}
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, OracleTraceTag.Exit, OracleTraceClassName.OracleBinary, OracleTraceFuncName.ctor);
			}
		}

		public static XmlQualifiedName GetXsdType(XmlSchemaSet schemaSet)
		{
			return new XmlQualifiedName("base64Binary", "http://www.w3.org/2001/XMLSchema");
		}

		XmlSchema IXmlSerializable.GetSchema()
		{
			return null;
		}

		void IXmlSerializable.ReadXml(XmlReader reader)
		{
			string attribute = reader.GetAttribute("null", "http://www.w3.org/2001/XMLSchema-instance");
			if (attribute == null || !XmlConvert.ToBoolean(attribute))
			{
				m_value = Convert.FromBase64String(reader.ReadElementString());
				m_bNotNull = true;
			}
			else
			{
				m_value = null;
				m_bNotNull = false;
			}
		}

		void IXmlSerializable.WriteXml(XmlWriter writer)
		{
			if (m_bNotNull)
			{
				writer.WriteString(Convert.ToBase64String(m_value));
			}
			else
			{
				writer.WriteAttributeString("xsi", "null", "http://www.w3.org/2001/XMLSchema-instance", "true");
			}
		}

		public override bool Equals(object obj)
		{
			if (ProviderConfig.m_bTraceLevelPublic)
			{
				Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Entry, OracleTraceClassName.OracleBinary, OracleTraceFuncName.Equals);
			}
			try
			{
				if (obj == null || obj.GetType() != typeof(OracleBinary))
				{
					return false;
				}
				return CompareTo(obj) == 0;
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Public, OracleTraceTag.Error, OracleTraceClassName.OracleBinary, OracleTraceFuncName.Equals, ex);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPublic)
				{
					Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Exit, OracleTraceClassName.OracleBinary, OracleTraceFuncName.Equals);
				}
			}
		}

		public int CompareTo(object obj)
		{
			if (ProviderConfig.m_bTraceLevelPublic)
			{
				Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Entry, OracleTraceClassName.OracleBinary, OracleTraceFuncName.CompareTo);
			}
			try
			{
				if (obj == null)
				{
					throw new ArgumentNullException("obj");
				}
				if (obj.GetType() != typeof(OracleBinary))
				{
					throw new ArgumentException("obj");
				}
				OracleBinary oracleBinary = (OracleBinary)obj;
				switch (InternalTypes.CompareNull(!m_bNotNull, !oracleBinary.m_bNotNull))
				{
				case CompareNullEnum.BothNull:
					return 0;
				case CompareNullEnum.FirstNullOnly:
					return -1;
				case CompareNullEnum.SecondNullOnly:
					return 1;
				default:
				{
					byte[] value = m_value;
					byte[] value2 = oracleBinary.m_value;
					int num = Math.Min(value.Length, value2.Length);
					for (int i = 0; i < num; i++)
					{
						if (value[i] != value2[i])
						{
							if (value[i] < value2[i])
							{
								return -1;
							}
							return 1;
						}
					}
					if (value.Length == value2.Length)
					{
						return 0;
					}
					if (value.Length < value2.Length)
					{
						return -1;
					}
					return 1;
				}
				}
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Public, OracleTraceTag.Error, OracleTraceClassName.OracleBinary, OracleTraceFuncName.CompareTo, ex);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPublic)
				{
					Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Exit, OracleTraceClassName.OracleBinary, OracleTraceFuncName.CompareTo);
				}
			}
		}

		public override int GetHashCode()
		{
			if (ProviderConfig.m_bTraceLevelPublic)
			{
				Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Entry, OracleTraceClassName.OracleBinary, OracleTraceFuncName.GetHashCode);
			}
			try
			{
				if (m_bNotNull)
				{
					return m_value.GetHashCode();
				}
				return 0;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPublic)
				{
					Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Exit, OracleTraceClassName.OracleBinary, OracleTraceFuncName.GetHashCode);
				}
			}
		}

		public override string ToString()
		{
			if (ProviderConfig.m_bTraceLevelPublic)
			{
				Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Entry, OracleTraceClassName.OracleBinary, OracleTraceFuncName.ToString);
			}
			try
			{
				if (m_bNotNull)
				{
					return GetType()?.ToString() + "(" + m_value.Length + ")";
				}
				return "null";
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Public, OracleTraceTag.Error, OracleTraceClassName.OracleBinary, OracleTraceFuncName.ToString, ex);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPublic)
				{
					Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Exit, OracleTraceClassName.OracleBinary, OracleTraceFuncName.ToString);
				}
			}
		}

		public static OracleBinary Concat(OracleBinary value1, OracleBinary value2)
		{
			if (ProviderConfig.m_bTraceLevelPublic)
			{
				Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Entry, OracleTraceClassName.OracleBinary, OracleTraceFuncName.Concat);
			}
			try
			{
				if (InternalTypes.CompareNull(!value1.m_bNotNull, !value2.m_bNotNull) != CompareNullEnum.BothNotNull)
				{
					return Null;
				}
				byte[] value3 = value1.m_value;
				byte[] value4 = value2.m_value;
				byte[] array = new byte[value3.Length + value4.Length];
				Array.Copy(value3, array, value3.Length);
				Array.Copy(value4, 0, array, value3.Length, value4.Length);
				return new OracleBinary(array);
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Public, OracleTraceTag.Error, OracleTraceClassName.OracleBinary, OracleTraceFuncName.Concat, ex);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPublic)
				{
					Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Exit, OracleTraceClassName.OracleBinary, OracleTraceFuncName.Concat);
				}
			}
		}

		public static bool Equals(OracleBinary value1, OracleBinary value2)
		{
			if (ProviderConfig.m_bTraceLevelPublic)
			{
				Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Entry, OracleTraceClassName.OracleBinary, OracleTraceFuncName.Equals);
			}
			try
			{
				return InternalTypes.CompareNull(!value1.m_bNotNull, !value2.m_bNotNull) switch
				{
					CompareNullEnum.BothNull => true, 
					CompareNullEnum.BothNotNull => value1.CompareTo(value2) == 0, 
					_ => false, 
				};
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Public, OracleTraceTag.Error, OracleTraceClassName.OracleBinary, OracleTraceFuncName.Equals, ex);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPublic)
				{
					Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Exit, OracleTraceClassName.OracleBinary, OracleTraceFuncName.Equals);
				}
			}
		}

		public static bool GreaterThan(OracleBinary value1, OracleBinary value2)
		{
			if (ProviderConfig.m_bTraceLevelPublic)
			{
				Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Entry, OracleTraceClassName.OracleBinary, OracleTraceFuncName.GreaterThan);
			}
			try
			{
				return value1.CompareTo(value2) > 0;
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Public, OracleTraceTag.Error, OracleTraceClassName.OracleBinary, OracleTraceFuncName.GreaterThan, ex);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPublic)
				{
					Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Exit, OracleTraceClassName.OracleBinary, OracleTraceFuncName.GreaterThan);
				}
			}
		}

		public static bool GreaterThanOrEqual(OracleBinary value1, OracleBinary value2)
		{
			if (ProviderConfig.m_bTraceLevelPublic)
			{
				Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Entry, OracleTraceClassName.OracleBinary, OracleTraceFuncName.GreaterThanOrEqual);
			}
			try
			{
				return value1.CompareTo(value2) >= 0;
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Public, OracleTraceTag.Error, OracleTraceClassName.OracleBinary, OracleTraceFuncName.GreaterThanOrEqual, ex);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPublic)
				{
					Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Exit, OracleTraceClassName.OracleBinary, OracleTraceFuncName.GreaterThanOrEqual);
				}
			}
		}

		public static bool LessThan(OracleBinary value1, OracleBinary value2)
		{
			if (ProviderConfig.m_bTraceLevelPublic)
			{
				Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Entry, OracleTraceClassName.OracleBinary, OracleTraceFuncName.LessThan);
			}
			try
			{
				return value1.CompareTo(value2) < 0;
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Public, OracleTraceTag.Error, OracleTraceClassName.OracleBinary, OracleTraceFuncName.LessThan, ex);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPublic)
				{
					Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Exit, OracleTraceClassName.OracleBinary, OracleTraceFuncName.LessThan);
				}
			}
		}

		public static bool LessThanOrEqual(OracleBinary value1, OracleBinary value2)
		{
			if (ProviderConfig.m_bTraceLevelPublic)
			{
				Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Entry, OracleTraceClassName.OracleBinary, OracleTraceFuncName.LessThanOrEqual);
			}
			try
			{
				return value1.CompareTo(value2) <= 0;
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Public, OracleTraceTag.Error, OracleTraceClassName.OracleBinary, OracleTraceFuncName.LessThanOrEqual, ex);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPublic)
				{
					Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Exit, OracleTraceClassName.OracleBinary, OracleTraceFuncName.LessThanOrEqual);
				}
			}
		}

		public static bool NotEquals(OracleBinary value1, OracleBinary value2)
		{
			if (ProviderConfig.m_bTraceLevelPublic)
			{
				Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Entry, OracleTraceClassName.OracleBinary, OracleTraceFuncName.NotEquals);
			}
			try
			{
				return value1.CompareTo(value2) != 0;
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Public, OracleTraceTag.Error, OracleTraceClassName.OracleBinary, OracleTraceFuncName.NotEquals, ex);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPublic)
				{
					Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Exit, OracleTraceClassName.OracleBinary, OracleTraceFuncName.NotEquals);
				}
			}
		}

		public static bool operator ==(OracleBinary value1, OracleBinary value2)
		{
			if (ProviderConfig.m_bTraceLevelPublic)
			{
				Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Entry, OracleTraceClassName.OracleBinary, OracleTraceFuncName.OperatorEqualTo);
			}
			try
			{
				return Equals(value1, value2);
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Public, OracleTraceTag.Error, OracleTraceClassName.OracleBinary, OracleTraceFuncName.OperatorEqualTo, ex);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPublic)
				{
					Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Exit, OracleTraceClassName.OracleBinary, OracleTraceFuncName.OperatorEqualTo);
				}
			}
		}

		public static bool operator >(OracleBinary value1, OracleBinary value2)
		{
			if (ProviderConfig.m_bTraceLevelPublic)
			{
				Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Entry, OracleTraceClassName.OracleBinary, OracleTraceFuncName.OperatorGreaterThan);
			}
			try
			{
				return GreaterThan(value1, value2);
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Public, OracleTraceTag.Error, OracleTraceClassName.OracleBinary, OracleTraceFuncName.OperatorGreaterThan, ex);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPublic)
				{
					Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Exit, OracleTraceClassName.OracleBinary, OracleTraceFuncName.OperatorGreaterThan);
				}
			}
		}

		public static bool operator >=(OracleBinary value1, OracleBinary value2)
		{
			if (ProviderConfig.m_bTraceLevelPublic)
			{
				Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Entry, OracleTraceClassName.OracleBinary, OracleTraceFuncName.OperatorGreaterThanOrEqualTo);
			}
			try
			{
				return GreaterThanOrEqual(value1, value2);
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Public, OracleTraceTag.Error, OracleTraceClassName.OracleBinary, OracleTraceFuncName.OperatorGreaterThanOrEqualTo, ex);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPublic)
				{
					Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Exit, OracleTraceClassName.OracleBinary, OracleTraceFuncName.OperatorGreaterThanOrEqualTo);
				}
			}
		}

		public static bool operator <(OracleBinary value1, OracleBinary value2)
		{
			if (ProviderConfig.m_bTraceLevelPublic)
			{
				Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Entry, OracleTraceClassName.OracleBinary, OracleTraceFuncName.OperatorLessThan);
			}
			try
			{
				return LessThan(value1, value2);
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Public, OracleTraceTag.Error, OracleTraceClassName.OracleBinary, OracleTraceFuncName.OperatorLessThan, ex);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPublic)
				{
					Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Exit, OracleTraceClassName.OracleBinary, OracleTraceFuncName.OperatorLessThan);
				}
			}
		}

		public static bool operator <=(OracleBinary value1, OracleBinary value2)
		{
			if (ProviderConfig.m_bTraceLevelPublic)
			{
				Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Entry, OracleTraceClassName.OracleBinary, OracleTraceFuncName.OperatorLessThanOrEqualTo);
			}
			try
			{
				return LessThanOrEqual(value1, value2);
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Public, OracleTraceTag.Error, OracleTraceClassName.OracleBinary, OracleTraceFuncName.OperatorLessThanOrEqualTo, ex);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPublic)
				{
					Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Exit, OracleTraceClassName.OracleBinary, OracleTraceFuncName.OperatorLessThanOrEqualTo);
				}
			}
		}

		public static bool operator !=(OracleBinary value1, OracleBinary value2)
		{
			if (ProviderConfig.m_bTraceLevelPublic)
			{
				Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Entry, OracleTraceClassName.OracleBinary, OracleTraceFuncName.OperatorNotEqualTo);
			}
			try
			{
				return NotEquals(value1, value2);
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Public, OracleTraceTag.Error, OracleTraceClassName.OracleBinary, OracleTraceFuncName.OperatorNotEqualTo, ex);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPublic)
				{
					Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Exit, OracleTraceClassName.OracleBinary, OracleTraceFuncName.OperatorNotEqualTo);
				}
			}
		}

		public static OracleBinary operator +(OracleBinary value1, OracleBinary value2)
		{
			if (ProviderConfig.m_bTraceLevelPublic)
			{
				Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Entry, OracleTraceClassName.OracleBinary, OracleTraceFuncName.OperatorPlus);
			}
			try
			{
				return Concat(value1, value2);
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Public, OracleTraceTag.Error, OracleTraceClassName.OracleBinary, OracleTraceFuncName.OperatorPlus, ex);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPublic)
				{
					Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Exit, OracleTraceClassName.OracleBinary, OracleTraceFuncName.OperatorPlus);
				}
			}
		}

		public static explicit operator byte[](OracleBinary value1)
		{
			if (ProviderConfig.m_bTraceLevelPublic)
			{
				Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Entry, OracleTraceClassName.OracleBinary, OracleTraceFuncName.OperatorByteArray);
			}
			try
			{
				if (value1.m_bNotNull)
				{
					return value1.m_value;
				}
				throw new OracleNullValueException();
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Public, OracleTraceTag.Error, OracleTraceClassName.OracleBinary, OracleTraceFuncName.OperatorByteArray, ex);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPublic)
				{
					Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Exit, OracleTraceClassName.OracleBinary, OracleTraceFuncName.OperatorByteArray);
				}
			}
		}

		public static implicit operator OracleBinary(byte[] value1)
		{
			if (ProviderConfig.m_bTraceLevelPublic)
			{
				Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Entry, OracleTraceClassName.OracleBinary, OracleTraceFuncName.ctor);
			}
			try
			{
				return new OracleBinary(value1);
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Public, OracleTraceTag.Error, OracleTraceClassName.OracleBinary, OracleTraceFuncName.ctor, ex);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPublic)
				{
					Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Exit, OracleTraceClassName.OracleBinary, OracleTraceFuncName.ctor);
				}
			}
		}
	}
}
